#include "modbus_host.h"
#include "modbus_lib.h"
#include "usart.h"
#include "log.h"
MODH_T g_tModH;
VARH_T g_tVarH;


void MODH_Deal(usart_cache* recv) {
#if 0
    LOG_DEBUG("ModbusHost recv cnt[%03d] \r\n", recv->cnt - 3);
    for(uint8_t i = 3; i < recv->cnt; i++) {
        LOG_DEBUG("%x ", recv->data[i]);
    }
    LOG_DEBUG("\r\n");
#endif
    MODH_Poll(&recv->data[3], recv->cnt - 3);
}

void MODH_Poll(uint8_t *data, uint16_t len) {
    memcpy(&g_tModH.RxBuf[0], &data[0], len);
    g_tModH.RxCount = len;

    uint16_t crc1;
    if (g_tModH.RxCount < 4) {
        goto err_ret;
    }

    /* 计算CRC校验和 */
    crc1 = CRC16_Modbus(g_tModH.RxBuf, g_tModH.RxCount);
    if (crc1 != 0) {
        goto err_ret;
    }

    /* 分析应用层协议 */
    MODH_AnalyzeApp();

err_ret:
    NULL;

}
void MODH_SendAckWithCRC(void) {
    uint16_t crc;

    crc = CRC16_Modbus(g_tModH.TxBuf, g_tModH.TxCount);
    g_tModH.TxBuf[g_tModH.TxCount++] = crc >> 8;
    g_tModH.TxBuf[g_tModH.TxCount++] = crc;
#if 0
    LOG_DEBUG("ModbusHost trans cnt[%03d] \r\n", g_tModH.TxCount);
    for(uint8_t i = 0; i < g_tModH.TxCount; i++) {
        LOG_DEBUG("%x ", g_tModH.TxBuf[i]);
    }
    LOG_DEBUG("\r\n");
#endif
    usart_485trans(BACKUP_485, &g_tModH.TxBuf[0], g_tModH.TxCount);
}
void MODH_AnalyzeApp(void) {
    switch (g_tModH.RxBuf[1]) /* 第2个字节 功能码 */
    {
    case 0x03: /* 读取保持寄存器 在一个或多个保持寄存器中取得当前的二进制值 */
        MODH_Read_03H();
        break;
    case 0x06: /* 读取保持寄存器 在一个或多个保持寄存器中取得当前的二进制值 */
        MODH_Read_06H();
        break;
    }
}
void MODH_Send01H(uint8_t _addr, uint16_t _reg, uint16_t _num)
{
    g_tModH.TxCount = 0;
    g_tModH.TxBuf[g_tModH.TxCount++] = _addr;		/* 从站地址 */
    g_tModH.TxBuf[g_tModH.TxCount++] = 0x01;		/* 功能码 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;	/* 寄存器编号 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg;		/* 寄存器编号 低字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8;	/* 寄存器个数 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _num;		/* 寄存器个数 低字节 */

    MODH_SendAckWithCRC();		/* 发送数据，自动加CRC */
    g_tModH.fAck01H = 0;		/* 清接收标志 */
    g_tModH.RegNum = _num;		/* 寄存器个数 */
    g_tModH.Reg01H = _reg;		/* 保存03H指令中的寄存器地址，方便对应答数据进行分类 */
}
void MODH_Read_01H(void)
{
    uint8_t bytes;
    uint8_t *p;

    if (g_tModH.RxCount > 0)
    {
        bytes = g_tModH.RxBuf[2];	/* 数据长度 字节数 */
        switch (g_tModH.Reg01H)
        {
        case Slave_REG_D01:
            if (bytes == 8)
            {
                p = &g_tModH.RxBuf[3];

                g_tVarH.D01 = BEBufToUint16(p);
                p += 2;	/* 寄存器 */
                g_tVarH.D02 = BEBufToUint16(p);
                p += 2;	/* 寄存器 */
                g_tVarH.D03 = BEBufToUint16(p);
                p += 2;	/* 寄存器 */
                g_tVarH.D04 = BEBufToUint16(p);
                p += 2;	/* 寄存器 */

                g_tModH.fAck01H = 1;
            }
            break;
        }
    }
}
void MODH_Send02H(uint8_t _addr, uint16_t _reg, uint16_t _num)
{
    g_tModH.TxCount = 0;
    g_tModH.TxBuf[g_tModH.TxCount++] = _addr;		/* 从站地址 */
    g_tModH.TxBuf[g_tModH.TxCount++] = 0x02;		/* 功能码 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;	/* 寄存器编号 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg;		/* 寄存器编号 低字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8;	/* 寄存器个数 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _num;		/* 寄存器个数 低字节 */

    MODH_SendAckWithCRC();		/* 发送数据，自动加CRC */
    g_tModH.fAck02H = 0;		/* 清接收标志 */
    g_tModH.RegNum = _num;		/* 寄存器个数 */
    g_tModH.Reg02H = _reg;		/* 保存03H指令中的寄存器地址，方便对应答数据进行分类 */
}
void MODH_Read_02H(void)
{
    uint8_t bytes;
    uint8_t *p;

    if (g_tModH.RxCount > 0)
    {
        bytes = g_tModH.RxBuf[2];	/* 数据长度 字节数 */
        switch (g_tModH.Reg02H)
        {
        case Slave_REG_T01:
            if (bytes == 6)
            {
                p = &g_tModH.RxBuf[3];

                g_tVarH.T01 = BEBufToUint16(p);
                p += 2;	/* 寄存器 */
                g_tVarH.T02 = BEBufToUint16(p);
                p += 2;	/* 寄存器 */
                g_tVarH.T03 = BEBufToUint16(p);
                p += 2;	/* 寄存器 */

                g_tModH.fAck02H = 1;
            }
            break;
        }
    }
}
void MODH_Send03H(uint8_t _addr, uint16_t _reg, uint16_t _num)
{
    g_tModH.TxCount = 0;
    g_tModH.TxBuf[g_tModH.TxCount++] = _addr; /* 从站地址 */
    g_tModH.TxBuf[g_tModH.TxCount++] = 0x03; /* 功能码 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8; /* 寄存器编号 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg; /* 寄存器编号 低字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8; /* 寄存器个数 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _num; /* 寄存器个数 低字节 */

    MODH_SendAckWithCRC(); /* 发送数据，自动加CRC */
    g_tModH.fAck03H = 0; /* 清接收标志 */
    g_tModH.RegNum = _num; /* 寄存器个数 */
    g_tModH.Reg03H = _reg; /* 保存03H指令中的寄存器地址，方便对应答数据进行分类 */

}
void MODH_Read_03H(void) {
    uint8_t bytes;
    uint8_t i = 1;
    uint8_t *p;
    if (g_tModH.RxCount > 0) {
        bytes = g_tModH.RxBuf[2]; /* 数据长度 字节数 */
        if (bytes != g_tModH.RegNum * 2) {
            return;
        }
        p = &g_tModH.RxBuf[3];
        switch (g_tModH.Reg03H) {
        case Slave_REG_P01:
            g_tVarH.P01 = BEBufToUint16(p);
            LOG_DEBUG("g_tVarH.P01 %d \r\n", g_tVarH.P01);
            p += 2; /* 寄存器 */
            if (i * 2 == bytes) {
                g_tModH.fAck03H = 1;
                break;
            }
            i++;
        case Slave_REG_P02:
            g_tVarH.P02 = BEBufToUint16(p);
            LOG_DEBUG("g_tVarH.P02 %d \r\n", g_tVarH.P02);
            p += 2; /* 寄存器 */
            if (i * 2 == bytes) {
                g_tModH.fAck03H = 1;
                break;
            }
            i++;
        case Slave_REG_P03:
            g_tVarH.P03 = BEBufToUint16(p);
            p += 2; /* 寄存器 */
            if (i * 2 == bytes) {
                g_tModH.fAck03H = 1;
                break;
            }
            i++;
        default:
            NULL;
        }
    }
}
void MODH_Send04H(uint8_t _addr, uint16_t _reg, uint16_t _num)
{
    g_tModH.TxCount = 0;
    g_tModH.TxBuf[g_tModH.TxCount++] = _addr;		/* 从站地址 */
    g_tModH.TxBuf[g_tModH.TxCount++] = 0x04;		/* 功能码 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;	/* 寄存器编号 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg;		/* 寄存器编号 低字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8;	/* 寄存器个数 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _num;		/* 寄存器个数 低字节 */

    MODH_SendAckWithCRC();		/* 发送数据，自动加CRC */
    g_tModH.fAck04H = 0;		/* 清接收标志 */
    g_tModH.RegNum = _num;		/* 寄存器个数 */
    g_tModH.Reg04H = _reg;		/* 保存03H指令中的寄存器地址，方便对应答数据进行分类 */
}
void MODH_Read_04H(void)
{
    uint8_t bytes;
    uint8_t *p;

    if (g_tModH.RxCount > 0)
    {
        bytes = g_tModH.RxBuf[2];	/* 数据长度 字节数 */
        switch (g_tModH.Reg04H)
        {
        case Slave_REG_T01:
            if (bytes == 2)
            {
                p = &g_tModH.RxBuf[3];

                g_tVarH.A01 = BEBufToUint16(p);
                p += 2;	/* 寄存器 */

                g_tModH.fAck04H = 1;
            }
            break;
        }
    }
}
void MODH_Send05H(uint8_t _addr, uint16_t _reg, uint16_t _value)
{
    g_tModH.TxCount = 0;
    g_tModH.TxBuf[g_tModH.TxCount++] = _addr;			/* 从站地址 */
    g_tModH.TxBuf[g_tModH.TxCount++] = 0x05;			/* 功能码 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;		/* 寄存器编号 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg;			/* 寄存器编号 低字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _value >> 8;		/* 寄存器值 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _value;			/* 寄存器值 低字节 */

    MODH_SendAckWithCRC();		/* 发送数据，自动加CRC */

    g_tModH.fAck05H = 0;		/* 如果收到从机的应答，则这个标志会设为1 */
}
void MODH_Read_05H(void)
{
    if (g_tModH.RxCount > 0)
    {
        if (g_tModH.RxBuf[0] == g_tModH.TxBuf[0])
        {
            g_tModH.fAck05H = 1;		/* 接收到应答 */
        }
    };
}

void MODH_Send06H(uint8_t _addr, uint16_t _reg, uint16_t _value)
{
    g_tModH.TxCount = 0;
    g_tModH.TxBuf[g_tModH.TxCount++] = _addr;			/* 从站地址 */
    g_tModH.TxBuf[g_tModH.TxCount++] = 0x06;			/* 功能码 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;		/* 寄存器编号 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg;			/* 寄存器编号 低字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _value >> 8;		/* 寄存器值 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _value;			/* 寄存器值 低字节 */

    MODH_SendAckWithCRC();		/* 发送数据，自动加CRC */

    g_tModH.fAck06H = 0;		/* 如果收到从机的应答，则这个标志会设为1 */
}


void MODH_Read_06H(void)
{
    if (g_tModH.RxCount > 0)
    {
        if(g_tModH.RxCount != g_tModH.RxCount) {
            return;
        }
        if(0 == memcmp(&g_tModH.TxBuf[0], &g_tModH.RxBuf[0], g_tModH.TxCount)) {
            g_tModH.fAck06H = 1;
        }
    }
}
void MODH_Send10H(uint8_t _addr, uint16_t _reg, uint8_t _num, uint8_t *_buf)
{
    uint16_t i;

    g_tModH.TxCount = 0;
    g_tModH.TxBuf[g_tModH.TxCount++] = _addr;		/* 从站地址 */
    g_tModH.TxBuf[g_tModH.TxCount++] = 0x10;		/* 从站地址 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;	/* 寄存器编号 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _reg;		/* 寄存器编号 低字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8;	/* 寄存器个数 高字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = _num;		/* 寄存器个数 低字节 */
    g_tModH.TxBuf[g_tModH.TxCount++] = 2 * _num;	/* 数据字节数 */

    for (i = 0; i < 2 * _num; i++)
    {
        if (g_tModH.TxCount > H_RX_BUF_SIZE - 3)
        {
            return;		/* 数据超过缓冲区超度，直接丢弃不发送 */
        }
        g_tModH.TxBuf[g_tModH.TxCount++] = _buf[i];		/* 后面的数据长度 */
    }

    MODH_SendAckWithCRC();	/* 发送数据，自动加CRC */
}
void MODH_Read_10H(void)
{
    /*
    	10H指令的应答:
    		从机地址                11
    		功能码                  10
    		寄存器起始地址高字节	00
    		寄存器起始地址低字节    01
    		寄存器数量高字节        00
    		寄存器数量低字节        02
    		CRC校验高字节           12
    		CRC校验低字节           98
    */
    if (g_tModH.RxCount > 0)
    {
        if (g_tModH.RxBuf[0] == g_tModH.TxBuf[0])
        {
            g_tModH.fAck10H = 1;		/* 接收到应答 */
        }
    }
}